/*
 * H264RtpUnPacker.cpp
 *
 *  Created on: 2018年4月21日
 *      Author: zhengboyuan
 */

#include "H264RtpUnPacker.h"

namespace av
{

H264RtpUnPacker::H264RtpUnPacker()
{
}

H264RtpUnPacker::~H264RtpUnPacker()
{
}

bool H264RtpUnPacker::open(int mediaType, int codec)
{
	m_format.m_codec = MEDIA_CODEC_H264;

	return true;
}

bool H264RtpUnPacker::unpack(RtpPacket& pktIn, MediaPacket& pktOut)
{
	static unsigned char s_startCode[] = { 0, 0, 0, 1};

	uint8_t* data = pktIn.data;
	int length = pktIn.size;

	uint8_t naluType = data[0] & 0x1F;
	bool fullPacket = false;
	bool keyFrame = (naluType == 5);
	if (naluType == 5)
	{
		keyFrame = true;
	}
	else if (naluType == 7)
	{
		keyFrame = false;
	}
	else if (naluType == 8)
	{
		keyFrame = false;
	}

	if (naluType == 28 || naluType == 29)
	{
		unsigned char startBit = data[1]&0x80;
		unsigned char endBit = data[1]&0x40;

		if( startBit )
		{
			naluType = ( data[0] & 0xE0 ) | ( data[1] & 0x1F );
			m_buffer.clear();
			m_buffer.write(s_startCode, sizeof(s_startCode));
			m_buffer.write(&naluType, 1);
		}
		else if (m_buffer.empty())
		{
			naluType = ( data[0] & 0xE0 ) | ( data[1] & 0x1F );
			m_buffer.clear();
			m_buffer.write(s_startCode, sizeof(s_startCode));
			m_buffer.write(&naluType, 1);
		}

		data += 2;
		length -= 2;

		m_buffer.write(data, length);

		if (endBit)
		{
			fullPacket = true;
			naluType = (m_buffer[sizeof(s_startCode)] & 0x1F);
			keyFrame = (naluType == 5);
		}
	}
	else
	{
		if (m_buffer.empty())
		{
			m_buffer.write(s_startCode, sizeof(s_startCode));
		}
		else
		{
			//size_t len = m_buffer.length();
		}

		m_buffer.write(data, length);
		fullPacket = true;
	}

	if (fullPacket)
	{
        ffmpeg::av_packet_copy_data(&pktOut, m_buffer.data(), m_buffer.size());

		pktOut.stream_index = MEDIA_TYPE_VIDEO;
		pktOut.dts = pktIn.ts;
		pktOut.duration = 0;

		if (keyFrame)
		{
			pktOut.flags = (pktOut.flags | MEDIA_FLAG_KEY);
		}

		if (naluType == 7)
		{
            pktOut.flags = (pktOut.flags | MEDIA_FLAG_KEY);
		}
		else if (naluType == 8)
		{
            pktOut.flags = (pktOut.flags | MEDIA_FLAG_KEY);
		}

		m_buffer.clear();
	}

	return fullPacket;
}

void H264RtpUnPacker::close()
{
	// pass
}

bool H264RtpUnPacker::getFormat(MediaFormat& format)
{
	format = m_format;
	return true;
}



} /* namespace av */
